﻿using LitJson;
using LT_Event;
using NET;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using UnityWebSocket;

public class WebSocketMgr : AbsWebSocketMgr
{
    private Dictionary<int, Type> m_MsgCodeToDataType = new Dictionary<int, Type>();

    private EventSys m_Event = new EventSys();

    public void RegisterWebNetMsg<T>(Enum code, Action<AbsWebSocketBody> handler, CancellationToken cancellationToken) where T : AbsWebSocketBody
    {
        int msgCode = (int)(code as ValueType);
        if (!m_MsgCodeToDataType.ContainsKey(msgCode))
        {
            m_MsgCodeToDataType.Add(msgCode, typeof(T));
        }
        m_Event.RegisterHandler(code, (tuple) =>
        {
            handler.Invoke((tuple as Tuple<AbsWebSocketBody>).Item1);
        }, cancellationToken);
    }

    public override void OnInit(ITuple tuple = null)
    {
        base.OnInit(tuple);
        RegisterWebNetMsg<WebHeartBeat>(EWebNetCode.HeartBeat, OnHeartBeat, TokenSource.Token);
    }

    public override void OnCloseHandle(object sender, CloseEventArgs e)
    {
        Connect("wss://echo.websocket.events");
        LTLog.W("短线重连...");
    }

    private void OnHeartBeat(IWebSocketBody data)
    {
        m_HeartBeatTick = DateTime.UtcNow.Second;
        LTLog.L("收到心跳回包时间:" + m_HeartBeatTick);
    }

    public override void OnErrorHandle(object sender, ErrorEventArgs e)
    {
        LTLog.L(e.ToString());
    }

    public override void OnMsgHandle(object sender, MessageEventArgs e)
    {
        byte[] data = e.RawData;
        var code = (EWebNetCode)BitConverter.ToInt32(data, 0);
        int msgCode = (int)code;
        if (m_MsgCodeToDataType.ContainsKey(msgCode))
        {
            string jsonStr = Encoding.UTF8.GetString(data, 4, data.Length - 4);
            Type msgDataType = m_MsgCodeToDataType[msgCode];
            AbsWebSocketBody body = JsonMapper.ToObject(jsonStr, msgDataType) as AbsWebSocketBody;
            LTLog.L($"收到消息:->{code}:{msgCode}");
            m_Event.Notify(code, Tuple.Create(body));
        }
    }

    private Timer m_HeartBeatTimer;
    private int TIME_OUT = 8;
    private int SEND_INTERVAL = 5000;
    private int m_HeartBeatTick = 0;

    public override void OnOpenHandle(object sender, OpenEventArgs e)
    {
        m_HeartBeatTick = DateTime.UtcNow.Second;
        m_HeartBeatTimer = new Timer(SendHeartBeat, null, 0, SEND_INTERVAL);
    }

    private void SendHeartBeat(object state)
    {
        var curTime = DateTime.UtcNow.Second;
        if ((curTime - m_HeartBeatTick) > TIME_OUT)
        {
            Disconnect();
            m_HeartBeatTimer?.Dispose();
            return;
        }
        LTGL.Ins.WebSocketMgr.SendMsg(EWebNetCode.HeartBeat, new WebHeartBeat { });
        LTLog.W("发送心跳包时间:" + curTime);
    }

    public void SendMsg(EWebNetCode code, IWebSocketBody body)
    {
        ValueType v = code;
        int msgCode = (int)v;
        byte[] codeByte = BitConverter.GetBytes(msgCode);
        byte[] msgBody = Encoding.UTF8.GetBytes(JsonMapper.ToJson(body));
        byte[] sendBuffer = new byte[codeByte.Length + msgBody.Length];
        Buffer.BlockCopy(codeByte, 0, sendBuffer, 0, codeByte.Length);
        Buffer.BlockCopy(msgBody, 0, sendBuffer, 4, msgBody.Length);
        SendMsg(sendBuffer);
    }

    public override void OnRemove()
    {
        m_HeartBeatTimer?.Dispose();
        base.OnRemove();
    }
}